]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
status/bluetooth: Show immediate feedback on toggle
authorFlorian Müllner <fmuellner@gnome.org>
Mon, 22 Aug 2022 22:06:42 +0000 (00:06 +0200)
committerMarge Bot <marge-bot@gnome.org>
Fri, 1 Sep 2023 11:37:04 +0000 (11:37 +0000)
Since commit 6a23e8ee0f4, we use the adapter state (that includes
transitional state) to indicate progress when a state change takes
a long time.

However on many systems, the delay happens on the rfkill side,
before a change request even reaches the adapter.

Address this by temporarily overriding the adapter-state with the
expected transitional state, until an actual adapter state change
occurs.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5773

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2815>

js/ui/status/bluetooth.js

index 1584e04683ceae40ace1acd839c5ee2ab11bc446..888592dc908490bfa45e409804bdcb0f1a108a5b 100644 (file)
@@ -24,6 +24,8 @@ const rfkillManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(RfkillManagerInterfa
 
 Gio._promisify(GnomeBluetooth.Client.prototype, 'connect_service');
 
+const STATE_CHANGE_FAILED_TIMEOUT_MS = 30 * 1000;
+
 const BtClient = GObject.registerClass({
     Properties: {
         'available': GObject.ParamSpec.boolean('available', '', '',
@@ -48,8 +50,10 @@ const BtClient = GObject.registerClass({
         this._client.connect('notify::default-adapter-powered', () => {
             this.notify('active');
         });
-        this._client.connect('notify::default-adapter-state',
-            () => this.notify('adapter-state'));
+        this._client.connect('notify::default-adapter-state', () => {
+            delete this._predictedState;
+            this.notify('adapter-state');
+        });
         this._client.connect('notify::default-adapter', () => {
             const newAdapter = this._client.default_adapter ?? null;
 
@@ -108,11 +112,30 @@ const BtClient = GObject.registerClass({
     }
 
     get adapter_state() {
+        if (this._predictedState !== undefined)
+            return this._predictedState;
         return this._client.default_adapter_state;
     }
 
     toggleActive() {
-        this._proxy.BluetoothAirplaneMode = this.active;
+        const {active} = this;
+
+        // on many systems, there's a significant delay until the rfkill
+        // state results in an adapter state change; work around that by
+        // overriding the current state with the expected transition
+        this._predictedState = active
+            ? AdapterState.TURNING_OFF
+            : AdapterState.TURNING_ON;
+        this.notify('adapter-state');
+
+        // toggling the state *really* should result in an adapter-state
+        // change eventually (even on error), but just to be sure to not
+        // be stuck with the overriden state, force a notify signal after
+        // a timeout
+        setTimeout(() => this._client.notify('default-adapter-state'),
+            STATE_CHANGE_FAILED_TIMEOUT_MS);
+
+        this._proxy.BluetoothAirplaneMode = active;
         if (!this._client.default_adapter_powered)
             this._client.default_adapter_powered = true;
     }